import pygame
import os
import math
from typing import Dict, Optional

class SoundManager:
    def __init__(self, config):
        self.config = config
        self.sounds: Dict[str, Optional[pygame.mixer.Sound]] = {}
        self.music: Optional[str] = None
        self.sound_enabled = True
        self.music_enabled = True
        self._load_sounds()
        self._load_default_sounds()
        
    def _load_sounds(self):
        """加载所有音效文件"""
        sound_files = {
            # 游戏音效
            'move': 'move.wav',
            'rotate': 'rotate.wav',
            'drop': 'drop.wav',
            'clear': 'clear.wav',
            'gameover': 'gameover.wav',
            # 界面音效
            'menu': 'menu.wav',
            'select': 'select.wav',
            # 背景音乐
            'bgm': 'bgm.mp3'
        }
        
        # 确保assets目录结构存在
        for dir_name in ['sounds', 'sounds/effects', 'sounds/music']:
            dir_path = os.path.join('assets', dir_name)
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
                print(f"Created directory: {dir_path}")
                
    def _load_default_sounds(self):
        """加载默认的内置音效"""
        default_sounds = {
            'move': self._generate_move_sound(),
            'rotate': self._generate_rotate_sound(),
            'drop': self._generate_drop_sound(),
            'clear': self._generate_clear_sound(),
            'gameover': self._generate_gameover_sound()
        }
        
        for name, sound in default_sounds.items():
            if name not in self.sounds or not self.sounds[name]:
                self.sounds[name] = sound
                
    def _generate_move_sound(self) -> pygame.mixer.Sound:
        """生成移动音效 - 简单的哔声"""
        buffer = bytes([
            127 if i < 100 else 0 
            for i in range(1000)
        ])
        return pygame.mixer.Sound(buffer=buffer)
        
    def _generate_rotate_sound(self) -> pygame.mixer.Sound:
        """生成旋转音效 - 清脆的短音"""
        buffer = bytes([
            int(127 * abs(math.sin(i * 0.1)))
            for i in range(2000)
        ])
        return pygame.mixer.Sound(buffer=buffer)
    
    def _generate_drop_sound(self) -> pygame.mixer.Sound:
        """生成落地音效 - 低沉的撞击音"""
        buffer = bytes([
            int(127 * abs(math.sin(i * 0.05)) * (1 - i/3000))
            for i in range(3000)
        ])
        return pygame.mixer.Sound(buffer=buffer)
    
    def _generate_clear_sound(self) -> pygame.mixer.Sound:
        """生成消除音效 - 欢快的上升音"""
        buffer = bytes([
            int(63 * abs(math.sin(i * 0.15)) + 
                63 * abs(math.sin(i * 0.2)))
            for i in range(4000)
        ])
        return pygame.mixer.Sound(buffer=buffer)
    
    def _generate_gameover_sound(self) -> pygame.mixer.Sound:
        """生成游戏结束音效 - 低沉的下降音"""
        buffer = bytes([
            int(127 * abs(math.sin(i * 0.025)) * (1 - i/5000))
            for i in range(5000)
        ])
        return pygame.mixer.Sound(buffer=buffer)
        
    def play(self, sound_name: str, volume: float = None):
        """播放音效,支持音量控制"""
        if not self.sound_enabled:
            return
            
        if sound_name in self.sounds and self.sounds[sound_name]:
            try:
                sound = self.sounds[sound_name]
                if volume is not None:
                    sound.set_volume(volume * self.config.config['volume'])
                else:
                    sound.set_volume(self.config.config['volume'])
                sound.play()
            except Exception as e:
                print(f"Warning: Failed to play sound {sound_name}: {str(e)}")
                
    def play_music(self, fade_ms: int = 1000):
        """播放背景音乐,支持淡入效果"""
        if not self.music_enabled or 'bgm' not in self.sounds:
            return
            
        try:
            pygame.mixer.music.load(self.sounds['bgm'])
            pygame.mixer.music.set_volume(self.config.config['volume'])
            pygame.mixer.music.play(-1, fade_ms=fade_ms)
        except Exception as e:
            print(f"Warning: Failed to play background music: {str(e)}")
            
    def stop_music(self, fade_ms: int = 1000):
        """停止背景音乐,支持淡出效果"""
        try:
            pygame.mixer.music.fadeout(fade_ms)
        except:
            pygame.mixer.music.stop()
            
    def toggle_sound(self, enabled: bool = None):
        """切换音效开关"""
        if enabled is not None:
            self.sound_enabled = enabled
        else:
            self.sound_enabled = not self.sound_enabled
            
    def toggle_music(self, enabled: bool = None):
        """切换音乐开关"""
        if enabled is not None:
            self.music_enabled = enabled
        else:
            self.music_enabled = not self.music_enabled
            
        if self.music_enabled:
            self.play_music()
        else:
            self.stop_music()
            
    def update_volume(self, volume: float):
        """更新音量"""
        self.config.config['volume'] = volume
        # 更新音效音量
        for sound in self.sounds.values():
            if sound:
                sound.set_volume(volume)
        # 更新音乐音量
        try:
            pygame.mixer.music.set_volume(volume)
        except:
            pass